/*
  testApproxLRU.c - Linux Paging Algorithm Test File
  Ben Marks, Chris Lekas

  Checks to see if page replacement behavior approximates an
  LRU behavior.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <linux/pgfltstats.h>

#include "common.h"


/* Idea: Read a section of memory larger than RAM (low, hi), but every
 *  5000 pages, reread a certain section (lowSmall, hiSmall) that has
 *  already been read in order to make sure that this section stays in
 *  RAM if LRU or a similar policy is being used.  Ideally, (lowSmall,
 *  hiSmall) should be near the beginning of the array of memory.
 *  After reading all of (low, hi), read (lowSmall, hiSmall) again.
 *  If this results in more than a few major page faults, the policy
 *  cannot be an approximation of LRU.  If few major page faults
 *  occur, the policy is not FIFO or MRU.
 *
 * Cutoff is used to ensure that, after a certain point, we stop
 * accessing the small portion, thus allowing it to potentially be
 * evicted if policy dicates. However, the relatively large value for
 * cutoff ensures that the smaller portion will be more recently used
 * than many other pages.
 */
void repeatedAccess(int low, int hi, int lowSmall, int hiSmall, 
		    int cutoff ) {

  int i, j;
  long unsigned first, second;
  
  for ( j = low; j < hi; j += 5000 ) {
    my_access( j, j+5000 );
    if ( j < cutoff ) {
      my_access( lowSmall, hiSmall );
    }
  }

}
/*
  Initialize memory, do specialized access pattern described above
  and then check number of faults encountered on access to 500
  pages both inside and outside of range of frequently accessed pages.
 */
int main(int argc, char ** argv) {
  
  init();

  repeatedAccess(0,          /* Start of large block */ 
		 70000,      /* End of large block */
		 0,          /* Start of small block */
		 500,       /* End of small block */
		 55000);     /* Cutoff for small block access */
  
  
  
  /* Check number of faults on access to frequently accessed subset 
     of pages */
  struct pf_info_struct before;
  if ( pgfltstats( getpid(), PGFLTSTAT_PROC, &before ) ) {
    perror("pgfltstats");
  }

  my_access( 0, 500 );

  struct pf_info_struct after;
  if ( pgfltstats( getpid(), PGFLTSTAT_PROC, &after ) ) {
    perror("pgfltstats");
  }

  // Begin reporting results
  printf("SmallRepeat\t%lu\t%lu\t", after.major - before.major,
	 after.minor - before.minor );

  /* Check number of faults on access outside of frequently accessed
     subset of pages */
  if ( pgfltstats( getpid(), PGFLTSTAT_PROC, &before ) ) {
    perror("pgfltstats");
  }

  my_access( 3000, 3500 );

  if ( pgfltstats( getpid(), PGFLTSTAT_PROC, &after ) ) {
    perror("pgfltstats");
  }


  // Report rest of results
  printf("%lu\t%lu\n", after.major - before.major,
	 after.minor - before.minor );

  

}
